﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SWGeneracionE.Models;
using System.Data.Objects;

namespace SWGeneracionE.Controllers
{
    public class ReporteController : BaseController
    {
        //
        // GET: /Reporte/ReporteParticipantes

        [Authorize]
        public ActionResult ReporteParticipantes()
        {
            return RedirectToAction("Participantes", "Participante");
        }

        //
        // GET: /Reporte/ReporteFinanciero

        [Authorize]
        public ActionResult ReporteFinanciero()
        {
            ReporteFinanciero rpt = new ReporteFinanciero();
            try
            {
                int idEvento = int.Parse(ViewBag.Evento);
                Evento evento = UoW.eventoRepository.FindFirst(e => e.idEvento == idEvento);
                rpt.nombreEvento = evento.nombre;
                rpt.cortesias = NumeroCortesias(idEvento);
                rpt.iBus = IngresoBus(idEvento).ToString(Constantes.SPECIFIER_N);
                rpt.iEventoBancoGTQ = IngresoEventoBancoLOC(idEvento).ToString(Constantes.SPECIFIER_N);
                rpt.iEventoBancoUSD = IngresoEventoBancoUSD(idEvento).ToString(Constantes.SPECIFIER_N);
                rpt.iEventoGTQ = IngresoEventoLOC(idEvento).ToString(Constantes.SPECIFIER_N);
                rpt.iEventoHotelGTQ = IngresoEventoHotelLOC(idEvento).ToString(Constantes.SPECIFIER_N);
                rpt.iEventoHotelUSD = IngresoEventoHotelUSD(idEvento).ToString(Constantes.SPECIFIER_N);
                rpt.iEventoUSD = IngresoEventoUSD(idEvento).ToString(Constantes.SPECIFIER_N);
                rpt.iRecaudacion = IngresoRecaudacion(idEvento).ToString(Constantes.SPECIFIER_N);
            }
            catch (Exception e)
            {
                ModelState.AddModelError("", e.Message);
                AgregarBitacora("Error ReporteFinanciero: " + e.Message + "--" + e.Source);
            }

            return View(rpt);
        }

        //
        // GET: /Reporte/ReporteFinanciero

        [Authorize]
        public ActionResult EstadisticasEvento()
        {
            Estadisticas rpt = new Estadisticas();
            try
            {
                int idEvento = int.Parse(ViewBag.Evento);
                Evento evento = UoW.eventoRepository.FindFirst(e => e.idEvento == idEvento);
                rpt.nombreEvento = evento.nombre;
                rpt.cortesias = NumeroCortesias(idEvento);
                rpt.pAuto = ParticipantesXTransporte(idEvento, Constantes.TIPOTRANSPORTE_AUTO);
                rpt.pBus = ParticipantesXTransporte(idEvento, Constantes.TIPOTRANSPORTE_BUS);
                rpt.pCancelados = ParticipantesXEstado(idEvento, Constantes.ESTADOPARTICIPANTE_CANCELADO);
                rpt.pInscritos = ParticipantesXEstado(idEvento, Constantes.ESTADOPARTICIPANTE_INSCRITO);
                rpt.pCasados = ParticipantesCasados(idEvento);
                rpt.pExterior = ParticipantesXPais(idEvento, false);
                rpt.pGuatemala = ParticipantesXPais(idEvento, true);
                rpt.pLocales = ParticipantesXIglesia(idEvento, c_iglesia_localcodigo);
                rpt.pMenores = ParticipantesMenores(idEvento);
                rpt.pNoMiembros = ParticipantesXIglesia(idEvento, c_iglesia_ningunacodigo);
                rpt.pRecaudacion = ParticipantesRecaudacion(idEvento);
            }
            catch (Exception e)
            {
                ModelState.AddModelError("", e.Message);
                AgregarBitacora("Error EstadisticasEvento: " + e.Message + "--" + e.Source);
            }

            return View(rpt);
        }

        #region "Funciones Adicionales"
        private int NumeroCortesias(int idEvento) {
            int cortesias = UoW.participanteXEventoRepository
                .FindBy(p => p.idEvento == idEvento && p.cortesia 
                && p.estado == Constantes.ESTADOPARTICIPANTE_INSCRITO)
                .Count();

            return cortesias;
        }
        private decimal IngresoEventoUSD(int idEvento)
        {
            decimal? ingreso = UoW.movimientoRepository
                .FindBy(p =>
                    (p.idEvento == idEvento)
                    && (p.idMotivo == Constantes.MOTIVODEPOSITO_EVENTO)
                    && (p.estado == Constantes.ESTADOMOVIMIENTO_AUTORIZADO))
                .Sum(p => p.montoUSD);

            return ingreso != null ?
                (decimal)ingreso
                : 0;
        }
        private decimal IngresoEventoLOC(int idEvento)
        {
            decimal? ingreso = UoW.movimientoRepository
                .FindBy(p =>
                    (p.idEvento == idEvento)
                    && (p.idMotivo == Constantes.MOTIVODEPOSITO_EVENTO)
                    && (p.estado == Constantes.ESTADOMOVIMIENTO_AUTORIZADO))
                .Sum(p => p.montoLOC);

            return ingreso != null ?
                (decimal)ingreso
                : 0;
        }
        private decimal IngresoEventoHotelUSD(int idEvento)
        {
            decimal? ingreso = UoW.movimientoRepository
                .FindBy(p =>
                    (p.idEvento == idEvento)
                    && (p.idMotivo == Constantes.MOTIVODEPOSITO_EVENTO)
                    && (p.idTipoPago == Constantes.TIPOMOVIMIENTO_PAGOHOTEL)
                    && (p.estado == Constantes.ESTADOMOVIMIENTO_AUTORIZADO))
                .Sum(p => p.montoUSD);

            return ingreso != null ?
                (decimal)ingreso
                : 0;
        }
        private decimal IngresoEventoHotelLOC(int idEvento)
        {
            decimal? ingreso = UoW.movimientoRepository
                .FindBy(p =>
                    (p.idEvento == idEvento)
                    && (p.idMotivo == Constantes.MOTIVODEPOSITO_EVENTO)
                    && (p.idTipoPago == Constantes.TIPOMOVIMIENTO_PAGOHOTEL)
                    && (p.estado == Constantes.ESTADOMOVIMIENTO_AUTORIZADO))
                .Sum(p => p.montoLOC);

            return ingreso != null ?
                (decimal)ingreso
                : 0;
        }
        private decimal IngresoEventoBancoUSD(int idEvento)
        {
            decimal? ingreso = UoW.movimientoRepository
                .FindBy(p =>
                    (p.idEvento == idEvento)
                    && (p.idMotivo == Constantes.MOTIVODEPOSITO_EVENTO)
                    && (p.idTipoPago != Constantes.TIPOMOVIMIENTO_PAGOHOTEL)
                    && (p.estado == Constantes.ESTADOMOVIMIENTO_AUTORIZADO))
                .Sum(p => p.montoUSD);

            return ingreso != null ?
                (decimal)ingreso
                : 0;
        }
        private decimal IngresoEventoBancoLOC(int idEvento)
        {
            decimal? ingreso = UoW.movimientoRepository
                .FindBy(p =>
                    (p.idEvento == idEvento)
                    && (p.idMotivo == Constantes.MOTIVODEPOSITO_EVENTO)
                    && (p.idTipoPago != Constantes.TIPOMOVIMIENTO_PAGOHOTEL)
                    && (p.estado == Constantes.ESTADOMOVIMIENTO_AUTORIZADO))
                .Sum(p => p.montoLOC);

            return ingreso != null ?
                (decimal)ingreso
                : 0;
        }
        private decimal IngresoRecaudacion(int idEvento)
        {
            decimal? ingreso = UoW.movimientoRepository
                .FindBy(p =>
                    (p.idEvento == idEvento)
                    && (p.idMotivo == Constantes.MOTIVODEPOSITO_RECAUDACION)
                    && (p.estado == Constantes.ESTADOMOVIMIENTO_AUTORIZADO))
                .Sum(p => p.montoLOC);

            return ingreso != null ?
                (decimal)ingreso
                : 0;
        }
        private decimal IngresoBus(int idEvento)
        {
            decimal? ingreso = UoW.movimientoRepository
                .FindBy(p =>
                    (p.idEvento == idEvento)
                    && (p.idMotivo == Constantes.MOTIVODEPOSITO_BUS)
                    && (p.estado == Constantes.ESTADOMOVIMIENTO_AUTORIZADO))
                .Sum(p => p.montoLOC);

            return ingreso != null ?
                (decimal)ingreso
                : 0;
        }

        private int ParticipantesRecaudacion(int idEvento)
        {
            int participantes = UoW.participanteXEventoRepository
                .FindBy(p => p.idEvento == idEvento && p.recaudacionS
                && p.estado == Constantes.ESTADOPARTICIPANTE_INSCRITO)
                .Count();

            return participantes;
        }
        private int ParticipantesXEstado(int idEvento, int estado)
        {
            int participantes = UoW.participanteXEventoRepository
                .FindBy(p => p.idEvento == idEvento 
                && p.estado == estado)
                .Count();

            return participantes;
        }
        private int ParticipantesMenores(int idEvento)
        {
            int participantes = UoW.participanteXEventoRepository
                .FindBy(p => p.idEvento == idEvento
                    && (DateTime.Now.Year - p.Participante.fechaNacimiento.Year +
                         (DateTime.Now < EntityFunctions.AddYears(p.Participante.fechaNacimiento, DateTime.Now.Year - p.Participante.fechaNacimiento.Year) ? -1 : 0)
                        ) < Constantes.MAYORIA_EDAD
                    && p.estado == Constantes.ESTADOPARTICIPANTE_INSCRITO)
                .Count();

            return participantes;
        }
        private int ParticipantesCasados(int idEvento)
        {
            int participantes = UoW.participanteXEventoRepository
                .FindBy(p => p.idEvento == idEvento
                    && p.Participante.estadoCivil == Constantes.ESTADOCIVIL_CASADO
                    && p.estado == Constantes.ESTADOPARTICIPANTE_INSCRITO)
                .Count();

            return participantes;
        }
        private int ParticipantesXIglesia(int idEvento, int idIglesia)
        {
            int participantes = UoW.participanteXEventoRepository
                .FindBy(p => p.idEvento == idEvento
                    && p.Participante.idIglesia == idIglesia
                    && p.estado == Constantes.ESTADOPARTICIPANTE_INSCRITO)
                .Count();

            return participantes;
        }
        private int ParticipantesXPais(int idEvento, bool bLocal)
        {
            int participantes = UoW.participanteXEventoRepository
                .FindBy(p => p.idEvento == idEvento
                    && (p.Participante.idPais == c_pais_localcodigo) == bLocal
                    && p.estado == Constantes.ESTADOPARTICIPANTE_INSCRITO)
                .Count();

            return participantes;
        }
        private int ParticipantesXTransporte(int idEvento, int tipoTransporte)
        {
            int participantes = UoW.participanteXEventoRepository
                .FindBy(p => p.idEvento == idEvento
                    && p.tipoTransporte == tipoTransporte
                    && p.estado == Constantes.ESTADOPARTICIPANTE_INSCRITO)
                .Count();

            return participantes;
        }
        #endregion

    }
}
